package com.github.thorqin.reader.utils

import android.app.Activity
import android.content.pm.PackageManager
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import com.github.thorqin.reader.App

private const val PERMISSION_REQUEST_CODE_MASK = 0xFF

object PermissionUtils {
	var permissionCallback = mutableMapOf<Int, (result: Boolean, lackedPermissions: Array<String>?) -> Unit>()

	/**s
	 * @param needPermissions Android permission strings, e.g.: android.permission.CAMERA, ...)
	 * can use Manifest.permission.XXX constant value
	 */
	fun ensurePermission(
		activity: Activity,
		needPermissions: Array<String>,
		onGranted: (result: Boolean, lackedPermissions: Array<String>?) -> Unit
	) {
		val requestPermissions = needPermissions.filter {
			val hasPermission: Int = ContextCompat.checkSelfPermission(activity, it)
			hasPermission != PackageManager.PERMISSION_GRANTED
		}.toTypedArray()
		if (requestPermissions.isEmpty()) {
			onGranted(true, null)
		} else {
			val reqCode = PERMISSION_REQUEST_CODE_MASK + permissionCallback.size
			permissionCallback[reqCode] = onGranted
			ActivityCompat.requestPermissions(
				activity, requestPermissions,
				reqCode
			)
		}
	}

	/**s
	 * @param needPermissions Android permission strings, e.g.: android.permission.CAMERA, ...)
	 * can use Manifest.permission.XXX constant value
	 */
	fun ensurePermission(
		fragment: Fragment,
		needPermissions: Array<String>,
		onGranted: (result: Boolean, lackedPermissions: Array<String>?) -> Unit
	) {
		val requestPermissions = needPermissions.filter {
			val hasPermission: Int = ContextCompat.checkSelfPermission(fragment.requireContext(), it)
			hasPermission != PackageManager.PERMISSION_GRANTED
		}.toTypedArray()
		if (requestPermissions.isEmpty()) {
			onGranted(true, null)
		} else {
			val reqCode = PERMISSION_REQUEST_CODE_MASK + permissionCallback.size
			permissionCallback[reqCode] = onGranted
			fragment.requestPermissions(requestPermissions, reqCode)
		}
	}

	fun onRequestPermissionsResult(
		requestCode: Int,
		permissions: Array<out String>,
		grantResults: IntArray
	) {
		val cb = permissionCallback[requestCode]
		if (cb != null) {
			when {
				grantResults.isEmpty() -> {
					cb(false, null)
				}
				grantResults.all {
					it == PackageManager.PERMISSION_GRANTED
				} -> {
					cb(true, null)
				}
				else -> {
					val lackedPermissions = grantResults.filter { it != PackageManager.PERMISSION_GRANTED }.mapIndexed { index, _ ->
						getPermissionLabel(permissions[index])
					}.filterNotNull().toTypedArray()
					cb(false, lackedPermissions)
				}
			}
		}
		permissionCallback.remove(requestCode)
	}

	fun getPermissionLabel(permission: String): String? {
		return try {
			return App.instance.packageManager.let {
				it.getPermissionInfo(permission, 0)?.loadLabel(it)?.toString()
			}
		} catch (e: Exception) {
			null
		}
	}

	fun getPermissionDescription(permission: String): String? {
		return try {
			App.instance.packageManager.let {
				it.getPermissionInfo(permission, 0)?.loadDescription(it)?.toString()
			}
		} catch (e: Exception) {
			null
		}
	}
}
